<?php
namespace App\Controllers;

use App\Models\User;
use App\Models\TokenBlacklist;
use App\Config\JwtConfig;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class UserController {
    private $userModel;
    private $tokenBlacklist;
    
    public function __construct() {
        $this->userModel = new User();
        $this->tokenBlacklist = new TokenBlacklist();
    }

    // 统一响应格式
    private function response($code = 0, $data = [], $message = 'success') {
        http_response_code($code === 0 ? 200 : 400);
        header('Content-Type: application/json');
        echo json_encode([
            'code' => $code,
            'data' => $data,
            'message' => $message
        ]);
    }
    
    /**
     * 验证用户名是否有效
     */
    public function validateUserId() {
        $data = json_decode(file_get_contents('php://input'), true);
        if (empty($data['user_id'])) {
            return $this->response(1001, [], '用户ID不能为空');
        }
        
        if ($this->userModel->existsUserId($data['user_id'])) {
            return $this->response(1002, [], '用户ID已存在'); // 使用与注册相同的错误码
        }
        
        // 返回传入的user_id，而不是空的$this->userModel->user_id
        return $this->response(0, ['user_id' => $data['user_id']], 'UserID 可用');
    }

    // 用户注册
    public function register() {
        $data = json_decode(file_get_contents("php://input"), true);

        // 验证请求数据
        if (empty($data['user_id']) || empty($data['username']) || empty($data['password'])) {
            return $this->response(1001, [], '用户ID、用户名和密码为必填项');
        }

        // 验证用户ID是否已存在
        if ($this->userModel->existsUserId($data['user_id'])){
            return $this->response(1002, [], '用户已注册');
        }

        $this->userModel->user_id = $data['user_id'];
        $this->userModel->username = $data['username'];
        $this->userModel->email = $data['email'] ?? '';
        $this->userModel->password_hash = password_hash($data['password'], PASSWORD_DEFAULT);
        $this->userModel->avatar_url = $data['avatar_url'] ?? 'https://ui-avatars.com/api/?name=' .$data['username']. '&background=random';

        // 执行注册
        if ($this->userModel->register()) {
            return $this->response(0, ['user_id' => $this->userModel->user_id], '注册成功');
        } else {
            return $this->response(1003, [], '注册失败');
        }
    }

    // 用户登录
    public function login() {
        $data = json_decode(file_get_contents('php://input'), true);

        // 验证请求数据
        if (empty($data['user_id']) || empty($data['password'])) {
            return $this->response(1004, [], '用户ID和密码为必填项');
        }

        // 查找用户
        $user = $this->userModel->findByUserId($data['user_id']);
        if (!$user) {
            return $this->response(1005, [], '用户不存在');
        }

        // 验证密码
        if ($data['password'] !== $user['password_hash']) {
            return $this->response(1006, [], '密码错误:' . $data['password']. ' != ' . $user['password_hash']);
        }

        // 生成访问Token和刷新Token
        $userData = [
            'id' => $user['id'],
            'user_id' => $user['user_id'],
            'username' => $user['username'],
            'avatar_url' => $user['avatar_url']
        ];

        $accessToken = JwtConfig::generateAccessToken($userData);
        $refreshToken = JwtConfig::generateRefreshToken($userData);

        return $this->response(0, [
            'user' => [
                'id' => $user['id'],
                'user_id' => $user['user_id'],
                'username' => $user['username'],
                'avatar_url' => $user['avatar_url']
            ],
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
            'expires_in' => JwtConfig::ACCESS_TOKEN_EXPIRES_IN,
            'refresh_expires_in' => JwtConfig::REFRESH_TOKEN_EXPIRES_IN
        ], '登录成功');
    }

    // 刷新Token
    public function refreshToken(){
        $data = json_decode(file_get_contents('php://input'), true);

        // 验证请求数据
        if (empty($data['refresh_token'])) {
            return $this->response(1007, [], '刷新Token为必填项');
        }

        try {
            // 验证刷新Token,这里会返回解码后的payload数据
            $decoded = JwtConfig::validateToken($data['refresh_token']);
            
            // 检查是否为刷新Token
            if (!JwtConfig::isRefreshToken($decoded)){
                return $this->response(1008, [], '无效的刷新Token');
            }

            // 检查Token是否已过期
            if (JwtConfig::isTokenExpired($decoded)){
                return $this->response(1009, [], '刷新Token已过期');
            }

            // 检查Token是否在黑名单中（已被撤销）
            if ($this->tokenBlacklist->isInBlacklist($decoded->jti)){
                return $this->response(1015, [], '刷新Token已被撤销');
            }

            // 生成新的访问Token（不生成新的刷新Token，提高安全性）
            $userData = (array)$decoded->data;
            $newAccessToken = JwtConfig::generateAccessToken($userData);
            
            return $this->response(0, [
                'access_token' => $newAccessToken,
                'expires_in' => JwtConfig::ACCESS_TOKEN_EXPIRES_IN
            ], 'Token刷新成功');

        }catch (\Exception $e) {
            return $this->response(1010, [], $e->getMessage());
        }
    }

    // 用户退出
    public function logout() {
        $data = json_decode(file_get_contents('php://input'), true);
        // 验证请求数据
        if (empty($data['access_token'])) {
            return $this->response(1016, [], '访问Token为必填项');
        }

        try {
            $decoded = JwtConfig::validateToken($data['access_token']);

            // 检查是否为访问Token
            if (!JwtConfig::isAccessToken($decoded)){
                return $this->response(1017, [], '无效的访问Token');
            }

            // 将Token加入黑名单
            $userId = $decoded->data->id;
            $addToBlacklistSuccess = $this->tokenBlacklist->addToBlacklist($decoded->jti, $userId, $decoded->exp);
            
            // 调用定期清理
            $this->tokenBlacklist->periodicCleanup();
            
            if (!$addToBlacklistSuccess) {
                error_log("Failed to add token to blacklist: " . $decoded->jti);
                return $this->response(1019, [], 'Token注销失败');
            }
            
            return $this->response(0, [], 'Token注销成功');
        } catch (\Exception $e) {
            return $this->response(1018, [], $e->getMessage());
        }
    }
}